"""
该模块主要：模拟postman发起请求，看是否能发送成功，和查看返回结果。
"""
import os

import jsonpath
import requests


from tools.handle_path import cases_data_images_dir
from handle_faker import HandleFaker


class ApiTest:

    """
        已注册的测试账号：
        1、管理员用户名：admin， pwd: 1234567a
        2、代理商用户名：科万代理商，pwd：Aa123456，注册手机号：15814479001，用户id：158583
        3、物业公司用户名：恒小物业， pwd：Aa123456，注册手机号：15814479002，用户id：158584
        4、业主用户名：{
            'ownerId': 2929,
            'userId': 158584,
            'ownerName': '袁克文',
            'idCard': '430665200011034156',
            'sex': 0,
            'age': 20,
            'phone': '15818879030',
            'communityId': 6817,
            'remark': '这是一个业主'
        }
    """

    # global_mobile_phone = "15814479007"       # 更改手机号，完成用户注册
    global_mobile_phone = HandleFaker().get_unregistered_phone()       # 未注册的手机号
    base_url = '接口主机地址，已屏蔽'  # 接口主机地址

    def __init__(self):
        # 请求头初始化，代码已屏蔽。
        pass

    # 01-1、文件相关操作，文件上传接口。
    def file_upload(self):
        url = self.base_url + '/file/upload'
        # 上传的文件参数, 关键字file要和服务器上要求的一致，可以到湘能物业swagger上看到，关键字要求的是file。
        file_name = "test_file_upload_01.jpg"
        file_path = os.path.join(cases_data_images_dir, file_name)
        image_file = {"file": (file_name, open(file_path, "rb"), "images/git")}
        # 发送请求
        response = requests.post(url=url, files=image_file)
        # 打印结果
        print(response.json())

    # 02-1、短信验证码相关操作
    # 步骤：短信验证码接口 发起请求，得到请求响应(含验证码)————>提取短信验证码
    def verification_code_message(self, mobile_phone=global_mobile_phone):
        mobile_phone_dict = {"phone": mobile_phone}
        url = self.base_url + '/verificationCode/message'
        res = requests.get(url=url, headers=self.headers_2, params=mobile_phone_dict)
        print('短信验证码相关操作接口，返回：', res.json())

        # 提取短信验证码，设置为类属性
        sms_verification_code = jsonpath.jsonpath(res.json(), "$.data")
        setattr(ApiTest, 'sms_verification_code', sms_verification_code[0])

        # 把接受短信验证码且未注册的手机号设置为类属性
        setattr(ApiTest, 'unregistered_mobile_phone', mobile_phone)

    # 03-1、系统用户相关操作，登录接口。
    # 步骤：用已经注册的用户名、密码，发起登录请求，得到响应结果。
    # 方法传参，方便登录不同权限的账户。
    def user_login(self, param_pwd, param_user_name):
        url = self.base_url + '/user/login'
        data = {"pwd": param_pwd, "userName": param_user_name}
        res = requests.post(url=url, json=data, headers=self.headers_2)
        self.headers_2["Authorization"] = "Bearer {}".format(res.json()['data']['token_info']['token'])
        print(f'系统用户相关操作————【{param_user_name}】登陆接口返回：{res.json()}')

        # 提取登录手机号码，设置为类属性
        login_phone = jsonpath.jsonpath(res.json(), "$..phone")
        setattr(ApiTest, 'login_phone', login_phone[0])

        # 提取登录用户id，设置为类属性
        login_id = jsonpath.jsonpath(res.json(), "$..id")
        setattr(ApiTest, 'login_id', login_id[0])

    # 03-2、系统用户相关操作。注册接口。
    # 步骤：短信验证码接口 发起请求，得到请求响应(含验证码)————>提取短信验证码————>发起注册接口请求。
    def user_register(self):
        self.verification_code_message()
        user_name = HandleFaker().get_unregistered_user_name()
        url = self.base_url + '/user/register'
        data = {
                "phone": ApiTest.unregistered_mobile_phone,
                "pwd": "Aa123456",
                "rePwd": "Aa123456",
                "userName": user_name,
                "verificationCode": ApiTest.sms_verification_code
        }
        res = requests.post(url=url, json=data, headers=self.headers_2)
        print('系统用户相关操作————注册接口返回：', res.json())

        # 提取注册手机号码，设置为类属性
        register_phone = jsonpath.jsonpath(res.json(), "$..phone")
        setattr(ApiTest, 'register_phone', register_phone[0])

        # 提取用户id，设置为类属性
        register_id = jsonpath.jsonpath(res.json(), "$..id")
        setattr(ApiTest, 'register_id', register_id[0])

        # 提取用户名，设置为类属性
        register_user_name = jsonpath.jsonpath(res.json(), "$..userName")
        setattr(ApiTest, 'register_user_name', register_user_name[0])

        # 把密码设置为类属性
        setattr(ApiTest, 'register_pwd', data.get('pwd'))

    # 04 - 商户信息相关操作，添加公司信息。merchant_type=2代表代理商 ，merchant_type=3代表物业，默认为3
    # 第一次登录时，需要添加公司信息，并选择属于代理商/物业公司
    def merchant_complete(self, merchant_type=3):
        # 步骤1、先注册
        self.user_register()
        # 步骤2、新用户，第一次登录
        self.user_login(ApiTest.register_pwd, ApiTest.register_user_name)
        # 生成随机的物业公司名字
        merchant_name = HandleFaker().random_property_company_name()
        # 步骤1、添加公司信息
        url = self.base_url + '/merchant/complete'
        data = {
                "address": "广东省深圳市南山区",
                "establishDate": "2021-10-02",
                "legalPerson": "深发展物业",
                "licenseCode": "xh430646464sdfa",
                "licenseUrl": "YingYeZhiZhao.jpg",
                "merchantName": merchant_name,
                "merchantType": merchant_type,
                "registerAuthority": "南山派出所",
                "tel": ApiTest.login_phone,
                "userId": ApiTest.login_id,
                "validityDate": "2033-05-02"
        }

        print(f"登录手机为：{ApiTest.login_phone}")
        print(f"登录id为：{ApiTest.login_id}")
        res = requests.put(url=url, json=data, headers=self.headers_2)
        print('商户信息相关操作————添加公司信息接口返回：', res.json())

    # 05-1、小区相关操作，添加小区。(代理商有添加小区的权限)
    # 步骤、代理商登录，获取到token和id———>发起请求
    def add_community(self):
        # 步骤1、代理商登录
        self.user_login('Aa123456', '科万代理商')
        # 步骤2、添加小区信息
        url = self.base_url + '/community/add'
        data = {
            "address": "广东省深圳市宝安区沙井蚂蚁5村",
            "communityName": "蚂蚁小区202111",
            "nearbyLandmarks": "海上田园",
            "userId": ApiTest.login_id
        }
        # print(f"代理商手机为：{ApiTest.login_phone}")
        # print(f"代理商id为：{ApiTest.login_id}")
        res = requests.post(url=url, json=data, headers=self.headers_2)
        print('小区相关操作————添加小区接口返回：', res.json())

        # 提取小区id号
        community_id = jsonpath.jsonpath(res.json(), "$..communityId")
        # 把小区号设置为类属性
        setattr(ApiTest, 'community_id', community_id[0])
        # 把小区名字设置为类属性
        setattr(ApiTest, 'community_name', data.get('communityName'))

    # 05-2、小区相关操作，审核小区，管理员才有审核权限。
    # 步骤、代理商添加小区后，管理员根据小区id号审核。有bug，物业公司、代理商登录后也有审核权限。
    def examine_community(self):
        self.add_community()        # 代理商添加小区
        self.user_login('1234567a', 'admin')
        # self.user_login('Aa123456', '科万代理商')
        # self.user_login('Aa123456', '恒小物业')
        # self.user_login('Aa123456', '袁克文')
        # print(self.headers_2)

        url = self.base_url + '/community/examine'
        data = {
            "communityId": ApiTest.community_id,
            "remark": "资质合适，审核通过。",
            "state": 1
        }
        res = requests.post(url=url, json=data, headers=self.headers_2)
        print('小区相关操作————审核小区接口返回：', res.json())

    # 05-3、小区相关操作，物业公司申请入驻小区。
    # 步骤：管理员审核通过，物业公司申请入驻小区。
    def in_community(self):
        self.examine_community()        # 管理员审核代理商添加的小区，并通过。
        self.user_login('Aa123456', '恒小物业')               # 物业公司登录。
        url = self.base_url + '/community/in'
        data = {
            "communityId": ApiTest.community_id,
            "userId": ApiTest.login_id
        }
        res = requests.post(url=url, params=data, headers=self.headers_2)
        print('小区相关操作————物业公司申请入驻小区接口返回：', res.json())

        # 提取物业公司申请入驻小区的工单号(commuMemberId)，设置为类属性
        commu_member_id = jsonpath.jsonpath(res.json(), "$..commuMemberId")
        setattr(ApiTest, 'commu_member_id', commu_member_id[0])

    # 05-4、小区相关操作，代理商审核入驻小区申请。
    # 步骤：物业公司申请入驻小区——>代理商审核入驻资格
    def examine_in_community(self):
        self.in_community()     # 物业公司申请入驻小区
        self.user_login('Aa123456', '科万代理商')  # 代理商登录。
        url = self.base_url + '/community/in/examine'
        data = {
            "commuMemberId": ApiTest.commu_member_id,
            "remark": "贵物业公司资质符合，审核通过。",
            "state": 1
        }
        res = requests.post(url=url, json=data, headers=self.headers_2)
        print('小区相关操作————代理商审核入驻小区申请，接口返回：', res.json())

    # 06-1、楼栋相关操作，添加楼栋。
    # 步骤：物业公司申请入驻成功后，添加楼栋信息。
    def add_building(self):
        self.examine_in_community()     # 代理商审核物业公司入驻，通过。
        self.user_login('Aa123456', '恒小物业')  # 物业公司登录，添加楼栋信息。
        url = self.base_url + '/building/add'
        data = {
            "buildingName": "1号楼",
            "buildingNum": "001",
            "communityId": ApiTest.community_id,
            "floorage": 300,
            "remark": "这是第一栋楼",
            "userId": ApiTest.login_id
        }
        res = requests.post(url=url, json=data, headers=self.headers_2)
        print('楼栋相关操作————添加楼栋，接口返回：', res.json())

        # 提取楼栋号buildingId，设置为类属性。
        building_id = jsonpath.jsonpath(res.json(), "$..buildingId")
        setattr(ApiTest, 'building_id', building_id[0])

    # 06-2、楼栋相关操作，查看楼栋信息列表。
    # 步骤：代理商、物业公司登录后，都可以查看到楼栋信息列表。
    def building_list(self, page=1, size=3):
        # self.user_login('Aa123456', '科万代理商')  # 代理商登录。
        self.user_login('Aa123456', '恒小物业')  # 物业公司登录。
        url = self.base_url + f'/building/{page}/{size}/list'
        res = requests.get(url=url, headers=self.headers_2)
        print('楼栋相关操作————查看楼栋信息列表，接口返回：', res.json())

    # 07-1、单元相关操作，添加单元。
    # 步骤：物业公司添加楼栋后，物业公司添加单元信息。
    def add_unit(self):
        self.add_building()     # 添加楼栋信息。
        url = self.base_url + '/unit/add'
        data = {
            "buildingId": ApiTest.building_id,
            "floorage": 160,
            "layerCount": 22,
            "lift": 1,
            "remark": "第一单元",
            "unitNum": "001",
            "userId": ApiTest.login_id
        }
        res = requests.post(url=url, json=data, headers=self.headers_2)
        print('单元相关操作————添加单元，接口返回：', res.json())

        # 提取单元号unitId，设置为类属性。
        unit_id = jsonpath.jsonpath(res.json(), "$..unitId")
        setattr(ApiTest, 'unit_id', unit_id[0])

    # 08-1、房屋相关操作，添加房屋。
    # 物业添加单元信息后，添加房屋信息。
    def add_room(self):
        self.add_unit()      # 物业公司添加单元信息
        url = self.base_url + '/room/add'
        data = {
            "builtUpArea": 90,
            "communityId": ApiTest.community_id,
            "layer": 15,
            "remark": "这是一个房间",
            "roomNum": "001",
            "roomStyle": "三室一厅",
            "unitId": ApiTest.unit_id,
            "userId": ApiTest.login_id
        }
        res = requests.post(url=url, json=data, headers=self.headers_2)
        print('房屋相关操作————添加房屋，接口返回：', res.json())

        # 提取房屋号roomId，设置为类属性。
        room_id = jsonpath.jsonpath(res.json(), "$..roomId")
        setattr(ApiTest, 'room_id', room_id[0])

    # 09-1、业主相关操作，添加业主。
    # 物业公司添加房屋信息后，添加业主信息。
    def add_owner(self):
        self.add_room()     # 物业公司添加房屋信息
        url = self.base_url + '/owner/add'
        data = {
            "age": 20,
            "communityId": ApiTest.community_id,
            "idCard": "430665200011034158",
            "ownerName": "袁克定",
            "phone": "15818889030",
            "remark": "这是一个业主",
            "sex": 0,
            "userId": ApiTest.login_id
        }

        res = requests.post(url=url, json=data, headers=self.headers_2)
        print('业主相关操作————添加业主，接口返回：', res.json())

        # 提取业主号ownerId，设置为类属性。
        owner_id = jsonpath.jsonpath(res.json(), "$..ownerId")
        setattr(ApiTest, 'owner_id', owner_id[0])
        # 把业主身份证、姓名、手机号设置为类属性
        setattr(ApiTest, 'owner_id_card', data.get('idCard'))
        setattr(ApiTest, 'owner_name', data.get('ownerName'))
        setattr(ApiTest, 'owner_phone', data.get('phone'))

    # 09-2、业主相关操作，绑定业主。
    # 物业公司添加业主信息后，绑定业主。
    def bind_owner(self):
        self.add_owner()    # 添加业主信息
        self.verification_code_message(mobile_phone=ApiTest.owner_phone)    # 获取短信验证码
        url = self.base_url + '/owner/bind'
        data = {
            "communityId": ApiTest.community_id,
            "communityName": ApiTest.community_name,
            "idCard": ApiTest.owner_id_card,
            "msgCode": ApiTest.sms_verification_code,
            "ownerName": ApiTest.owner_name,
            "phone": ApiTest.owner_phone,
            "pwd": "Aa123456"
        }
        res = requests.post(url=url, json=data, headers=self.headers_2)
        print('业主相关操作————绑定业主，接口返回：', res.json())

    # 09-3、业主相关操作，业主入驻房屋。
    # 物业公司绑定业主后，物业公司再添加业主入驻信息。
    def check_in_owner(self):
        self.bind_owner()   # 物业公司绑定业主
        url = self.base_url + '/owner/checkIn'
        data = {
            "ownerId": ApiTest.owner_id,
            "roomId": ApiTest.room_id,
            "userId": ApiTest.login_id
        }
        res = requests.post(url=url, json=data, headers=self.headers_2)
        print('业主相关操作————业主入驻房屋，接口返回：', res.json())

    # 09-4、业主相关操作，业主登录。
    # 物业公司添加业主入驻信息后，业主登录。
    def owner_login(self, phone, pwd, is_check_in=True):
        if is_check_in is False:
            self.check_in_owner()  # 物业公司添加业主入驻信息
            data = {
                "phone": ApiTest.owner_phone,
                "pwd": "Aa123456"
            }
        else:
            data = {
                "phone": phone,
                "pwd": pwd
            }

        url = self.base_url + '/owner/login'

        res = requests.post(url=url, json=data, headers=self.headers_2)
        self.headers_2["Authorization"] = "Bearer {}".format(res.json()['data']['token_info']['token'])
        print('业主相关操作————业主登录，接口返回：', res.json())

        # 提取登录手机号码，设置为类属性
        owner_login_phone = jsonpath.jsonpath(res.json(), "$..phone")
        setattr(ApiTest, 'owner_login_phone', owner_login_phone[0])

        # 提取登录用户id，设置为类属性
        owner_login_id = jsonpath.jsonpath(res.json(), "$..id")
        setattr(ApiTest, 'owner_login_id', owner_login_id[0])

    # 09-5、业主相关操作，我的房屋。业主登录后查看我的房屋。
    def owner_room(self):
        self.owner_login('15818879030', 'Aa123456')      # 业主登录
        userId = ApiTest.owner_login_id     # 业主登录后返回的id
        url = self.base_url + f'/owner/room/{userId}'
        res = requests.get(url=url, headers=self.headers_2)
        print('业主登录后查看我的房屋，接口返回：', res.json())

        # 提取业主所拥有的全部房屋信息。 jsonpath提取表达式：$.data[*]
        owner_room_list = jsonpath.jsonpath(res.json(), "$.data[*]")
        setattr(ApiTest, 'owner_room_list', owner_room_list)

    # 10-1、旧货、需求发布相关操作。
    # 业主登录后，发布旧货、需求。
    def junk_requirement_publish(self):
        self.owner_login('15818879030', 'Aa123456')  # 业主登录
        url = self.base_url + '/junkRequirement/publish'
        data = {
            "classification": 2,
            "communityId": 6817,
            "context": "求购一张书桌",
            "publishUserLink": "15808569874",
            "referencePrice": 200,
            "type": 2,
            "userId": ApiTest.owner_login_id
        }

        res = requests.post(url=url, json=data, headers=self.headers_2)
        print('业主相关操作————旧货、需求发布相关操作，接口返回：', res.json())

    # 11-1、出租相关操作
    # 业主登录后，发布房屋出租信息。
    def rent_room_publish(self):
        self.owner_login('15818879030', 'Aa123456')  # 业主登录
        self.owner_room()   # 得到业主所拥有的房屋

        url = self.base_url + '/rent/room/publish'
        data = {
            "checkIn": 1,
            "communityId": ApiTest.owner_room_list[0]['communityId'],
            "communityName": "蚂蚁5村小区",
            "ownerName": "袁克文",
            "ownerTel": "15818879030",
            "paymentType": 2,
            "price": 800,
            "rentDesc": "家电齐全，周边配套设置应有尽有，生活、上班都方便，只等你来！",
            "rentTitle": "豪华三房，拎包入住！",
            "rentingType": 1,
            "roomId": ApiTest.owner_room_list[0]['roomId']
        }

        res = requests.post(url=url, json=data, headers=self.headers_2)
        print('业主相关操作————发布房屋出租信息，接口返回：', res.json())


# 测试代码
if __name__ == '__main__':
    a = ApiTest()
    # a.file_upload()
    # a.verification_code_message()
    # a.user_register()
    # a.user_login('Aa123456', '恒小物业')     # 更换密码，用户名，不用身份的账户登录
    # a.merchant_complete()
    # a.add_community()
    # a.examine_community()
    # a.in_community()
    # a.examine_in_community()
    # a.add_building()
    # a.building_list()
    # a.add_unit()
    # a.add_room()
    # a.add_owner()
    # a.bind_owner()
    # a.check_in_owner()
    # a.owner_login('15818879030', 'Aa123456')
    # a.owner_room()
    # a.junk_requirement_publish()
    # a.rent_room_publish()
